package failover

import (
	"context"
	"sync/atomic"
	"webook/internal/service/sms"
)

// FailOverSmsServiceV3 拥有失败处理的短信发送装饰器第三种实现
type FailOverSmsServiceV3 struct {
	svcs      []sms.Service
	startIdx  uint64 // 轮询的起始下标
	count     uint32 // 连续超时次数
	threshold uint32 // 超时阈值
}

func NewFailOverSmsServiceV3(svcs []sms.Service) *FailOverSmsServiceV3 {
	return &FailOverSmsServiceV3{
		svcs:      svcs,
		startIdx:  -1,
		threshold: 3,
		count:     0,
	}
}

func (f *FailOverSmsServiceV3) Send(ctx context.Context, phone string, templateCode string, templateParam string) error {
	// 获取当前超时次数
	curCount := atomic.LoadUint32(&f.count)
	curIdx := atomic.LoadUint64(&f.startIdx)
	if curCount >= f.threshold {
		// 应该更换运营商
		newIdx := curIdx + 1
		if atomic.CompareAndSwapUint64(&f.startIdx, curIdx, newIdx) {
			// 重置超时次数
			atomic.StoreUint32(&f.count, 0)
		} else {
			// 此处说明并发竞争失败
		}
		curIdx = newIdx
	}
	err := f.svcs[curIdx].Send(ctx, phone, templateCode, templateParam)
	switch err {
	case nil:
		atomic.StoreUint32(&f.count, 0)
		return nil
	case context.DeadlineExceeded:
		atomic.AddUint32(&f.count, 1)
	default:
		// 针对其他情况做特殊处理
	}
	return err

}
